package com.joelbitar.switchctrl;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.util.Log;

public class Request {
	private Server server;
	private ArrayList<Device> on = new ArrayList<Device>();
	private ArrayList<Device> off = new ArrayList<Device>();
	// TODO should probably be a list of servers on which to get the lists
	private boolean list = false;
	// TODO should not be needed if the list is a list of servers.
	private boolean sendList = false;
	
	private static final String JSON_USERNAME = "u";
	private static final String JSON_PASSWORD = "p";
	private static final String JSON_LIST = "list";
	private static final String JSON_ON = "on";
	private static final String JSON_OFF = "off";

	public Server getServer() {
		return server;
	}
	public void setServer(Server server) {
		this.server = server;
	}
	
	public String getPassword(){
		return this.server.getEncryptedPassword();
	}
	
	public String getUsername() {
		return this.server.getUsername();
	}
	
	public ArrayList<Device> getOn() {
		return on;
	}
	public void setOn(ArrayList<Device> on) {
		this.on = on;
	}
	public ArrayList<Device> getOff() {
		return off;
	}
	public void setOff(ArrayList<Device> off) {
		this.off = off;
	}
	public boolean shouldList() {
		return this.getList();
	}
	public boolean getList() {
		return list;
	}
	public void setList(boolean list) {
      this.setSendList(true);
		this.list = list;
	}
   
   public void setSendList(boolean sendList) {
      this.sendList = sendList;
   }

   public boolean shouldSendList() {
      return this.sendList;
   }
   
   public JSONObject getRequestObject() throws JSONException {
      JSONObject json = new JSONObject();
      json.put(JSON_USERNAME, this.getUsername());
      json.put(JSON_PASSWORD, this.getPassword());
      
      // If should send list parameter at all
      if(this.shouldSendList()) {
         json.put(JSON_LIST, this.getList());
      }
      
      if(this.on.size() > 0)
      {
         JSONArray on = new JSONArray(this.on);
         json.put(JSON_ON, on);
      }
      
      if(this.off.size() > 0)
      {
         JSONArray off = new JSONArray(this.off);
         json.put(JSON_OFF, off);
      }
      
      return json;
   }
   
   public String getRequestString() {
	   JSONObject json = new JSONObject();
	   
	   try {
		   json = this.getRequestObject();
	   } catch (JSONException e) {
		   // TODO Auto-generated catch block
		   e.printStackTrace();
	   }
  
      return json.toString();
   }
   
   private String buildGetString(String s, String a, String b)
   {
	   if(s.length() > 0)
	   {
		   s += "&";
	   }
	   
	   return s += a + "=" + b;
   }
   
   public List<NameValuePair> getRequestNameValuePairs() {
	   
	   List<NameValuePair> np = new ArrayList<NameValuePair>();
	   
	   np.add(new BasicNameValuePair(Request.JSON_USERNAME, this.getUsername()));
	   np.add(new BasicNameValuePair(Request.JSON_PASSWORD, this.getPassword()));

	   // If should send list parameter at all
	   if(this.shouldSendList()) {
		   // Add "true" or "false" (as string)
		   np.add(new BasicNameValuePair(Request.JSON_LIST, (this.getList()) ? "true" : "false"));
	   }
	  
	   if(this.on.size() > 0)
	   {
		   String ons = "";
		   for(int i = 0; i < this.on.size(); i ++)
		   {
			   if(i > 0)
			   {
				   ons += ",";
			   }
			   Device d = on.get(i);
			   ons += "" + d.getDevice_id();
			   
		   }
		   np.add(new BasicNameValuePair(Request.JSON_ON, ons));
	   }
	  
	  if(this.off.size() > 0)
	  {
		   String offs = "";
		   for(int i = 0; i < this.off.size(); i ++)
		   {
			   if(i > 0)
			   {
				   offs += ",";
			   }
			   Device d = off.get(i);
			   offs += "" + d.getDevice_id();
			   
		   }
		   np.add(new BasicNameValuePair(Request.JSON_OFF, offs));
	  }
	  
	  return np;
   }
   
   public String getRequestGetString() {
	   String s = "";

	   s =  this.buildGetString(s,JSON_USERNAME, this.getUsername());
	   s =  this.buildGetString(s,JSON_PASSWORD, this.getPassword());
	   
	   // If should send list parameter at all
	   if(this.shouldSendList()) {
		   s = this.buildGetString(s, JSON_LIST, "" + this.getList());
	   }
	  
	   if(this.on.size() > 0)
	   {
		   String ons = "";
		   for(int i = 0; i < this.on.size(); i ++)
		   {
			   if(i > 0)
			   {
				   ons += ",";
			   }
			   Device d = on.get(i);
			   ons += "" + d.getDevice_id();
			   
		   }
		   s = this.buildGetString(s, "on", ons);
	   }
	  
	  if(this.off.size() > 0)
	  {
		   String offs = "";
		   for(int i = 0; i < this.off.size(); i ++)
		   {
			   if(i > 0)
			   {
				   offs += ",";
			   }
			   Device d = off.get(i);
			   offs += "" + d.getDevice_id();
			   
		   }
		   s = this.buildGetString(s, "off", offs);
	  }
      return s;
   }
   
   /* 
    * Splits this request object into several requests objects
    * They are divided acording to which server the commands are on
    * 
    * */
   
   private Integer indexOfServerOnRequests(ArrayList<Request> requests, Server server)
   {
	   Log.i("indedofserveronrequests", "Getting index of the serveron the requestobjects");
	   if(requests.size() > 0)
	   {
		   for(int i = 0; i < requests.size(); i += 1)
		   {
			   Log.i("request", "Request numbero: " + i);
			   
			   Request request = requests.get(i);

			   Log.i("request", "Server of the request: " + request.getServer().getName());
			   Log.i("request", "Server to check (id): " + server.getId() + " server of request (id) :" + request.getServer().getId());
			   
			   if(request.getServer().getId() == server.getId())
			   {

				   Log.i("indexofserveronrequest", "Wawauwiwau, found server at inded: " + i);
				   return i;
			   }
		   }
	   }
	   
	   Log.i("indexofserveronrequest", "nothing found... ");
	   
	   return -1;
   }
   
   public ArrayList<Request> splitRequest() {
	   ArrayList<Request> requestObjects = new ArrayList<Request>();

	   if(this.on.size() > 0)
	   {
		   Log.i("splitrequest", "Ons: " + this.on.size());
		   for(int i = 0; i < on.size(); i += 1)
		   {
			   Device device = on.get(i);
			   Server server = device.getServer();
			   
			   Log.i("adding", "Adding device to ON list: " + device.getName());
			   
			   Integer index = indexOfServerOnRequests(requestObjects, server);
			   
			   if(index >= 0)
			   {
				   Log.i("adding", "Adding device to already existing RequestObject");
				   Request request = requestObjects.get(index);
				   request.addOn(device);
			   }
			   else
			   {
				   Log.i("adding", "Creating a new request, adding with the server: " + server.getName());
				   Request request = new Request();
				   request.addOn(device);
				   request.setServer(server);
				   requestObjects.add(request);
			   }
		   }
	   }
	   
	   if(this.off.size() > 0)
	   {
		   for(int i = 0; i < off.size(); i += 1)
		   {
			   Device device = off.get(i);
			   Server server = device.getServer();
			   
			   Integer index = indexOfServerOnRequests(requestObjects, server);
			   
			   if(index >= 0)
			   {
				   Request request = requestObjects.get(index);
				   request.addOff(device);
			   }
			   else
			   {
				   Request request = new Request();
				   request.addOff(device);
				   request.setServer(device.getServer());
				   requestObjects.add(request);
			   }
		   }
	   }
	   
	   Log.i("requestobjects", "Im done");
	   
	   return requestObjects;
   }
   
   public void addOff(Device device) {
	// TODO Auto-generated method stub
	   if(this.isInOffList(device) == false){
		   this.off.add(device);
	   }
   }
   
   public void addOn(Device device) {
	   // TODO Auto-generated method stub
	   if(this.isInOnList(device) == false){
		   Log.i("addon", "Adding to on list");
		   this.on.add(device);
	   }
	   else
	   {
		   Log.i("addon", "Wanted to add to on list, but was already there");
	   }
   }
   
   public boolean isInOnList(Device device)
   {
	   if(this.on.size() > 0)
	   {
		   Log.i("isinonlist", "Bigger than 0");
		   
		   if(this.on.indexOf(device) >= 0)
		   {
			   Log.i("isinofflist", "atIndex: " + this.on.indexOf(device));
			   return true;
		   }
	   }
	   else
	   {
		   Log.i("isinofflist", "Nothing in list");
	   }
	   return false;
   }

   public void removeFromOffList(Device device)
   {

	   if(this.off.size() > 0)
	   {
		   Log.i("removefromnofflist", "Size: " + this.off.size());
		   
		   if(this.off.indexOf(device) >= 0)
		   {
			   Log.i("removefromofflist", "At inded: " + this.off.indexOf(device));
			   this.off.remove(this.off.indexOf(device));
		   }
		   
		   Log.i("removefromnofflist", "After Size: " + this.off.size());
	   }
   }
   
   public void removeFromOnList(Device device)
   {

	   if(this.on.size() > 0)
	   {
		   Log.i("removefromnonlist", "Size: " + this.on.size());
		   
		   if(this.on.indexOf(device) >= 0)
		   {
			   Log.i("removefromofflist", "At inded: " + this.on.indexOf(device));
			   this.on.remove(this.on.indexOf(device));
		   }
		   
		   Log.i("removefromnofflist", "After Size: " + this.on.size());
	   }
   }
   
   public boolean isInOffList(Device device)
   {
	   if(this.off.size() > 0)
	   {
		   Log.i("isinofflist", "Bigger than 0");
		   
		   if(this.off.indexOf(device) >= 0)
		   {
			   Log.i("isinofflist", "atIndex: " + this.off.indexOf(device));
			   return true;
		   }
	   }
	   else
	   {
		   Log.i("isinofflist", "Nothing in list");
	   }
	   return false;
   	}
   
   	public String getUrl() {
	   return this.server.getHosturl();
   	}
	public void clear() {
		this.on.clear();
		this.off.clear();
	}
	public ArrayList<Device> getAllDevices() {
		ArrayList<Device> devices = new ArrayList<Device>();
		
		if(this.getOn().size() > 0)
			devices.addAll(this.getOn());
		
		if(this.getOff().size() > 0)
			devices.addAll(this.getOff());
		
		return devices;
	}
}
